package com.fg.cloud.framework.system;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fg.cloud.common.CommonConstants;
import com.fg.cloud.common.ServiceException;
import com.fg.cloud.common.StatusCode;
import com.fg.cloud.common.construction.Tree;
import com.fg.cloud.common.finals.UserType;
import com.fg.cloud.common.quantity.ResultType;
import com.fg.cloud.common.shiro.CustomLoginToken;
import com.fg.cloud.common.shiro.UserUtils;
import com.fg.cloud.framework.controller.BaseController;
import com.fg.cloud.manager.entry.factory.FactoryUserEntity;
import com.fg.cloud.manager.entry.system.vo.SystemUserVo;
import com.fg.cloud.manager.service.system.MenuService;

/**
 * @author ：
 * @date ： 2017年6月5日 下午1:49:43
 * @Description ：用户登录
 */
@Controller
public class LoginController extends BaseController {

	@Autowired
	private MenuService menuService;
	
	
	//@RequiresRoles(value=UserType.SYSTEM)
	@RequestMapping(value = "/")
    public String index() {
    	if (!SecurityUtils.getSubject().isAuthenticated()) {
            return "login";
        } else if (!(UserUtils.getCurrentUser() instanceof SystemUserVo)) {
        	return "login";
        }
        return "index";
    }

	/**
	 * 跳转到登录页面
	 */
	@RequestMapping("/tologin")
	public String showLogin() {
		System.out.println("===系统登录界面========");
		return "login";
	}
	
	/**
     * 首页
     * @param model
     * @return
     */
    @RequestMapping(value = "/index")
    public String index(Model model, HttpSession session) {
    	FactoryUserEntity user = getCurrentFactoryUser();
    	List<Tree> listMenus = null;
		if (1 == user.getUserType()) { // 1 厂商 : 厂商权限菜单
			//listMenus = menuService.findByUserId(user.getId(), 1);
		} else {// 0 平台用户: 具有平台用户权限菜单
			listMenus = menuService.findAllMenu(0);
		}

		model.addAttribute("listMenus", listMenus);
		model.addAttribute("user", user);
    	
        return "/index";
    }
	
	/**
	 * 用户登录
	 * 
	 * @param request
	 * @param response
	 * @param userName用户名
	 * @param password密码
	 * @return
	 * @throws IOException 
	 */
	@RequestMapping(value="/factoryLogin", method = {RequestMethod.POST, RequestMethod.GET})
	@ResponseBody
	public void login(HttpServletRequest request, HttpServletResponse response, 
			String userName, String password, String type, String code) throws IOException {
		System.out.println("===用户登录功能========");
		
		if(StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)) {
			doResult(response, false, null, "用户名或密码不能为空");
            return;
		}
		//System.out.println(request.getServletPath());
		//System.out.println(request.getSession().getServletContext().getRealPath("/"));
		//System.out.println(request.getSession().getServletContext().getContextPath());
		
		// 校验验证码
		/*String sessionCode = (String) request.getSession().getAttribute("code");
		if (!StringUtils.equals(sessionCode, code)) {
			doResult(response, false, null, "用户名不存在");
			return;
		}*/
		
		
		//若Authenticated已经验证通过，则不再次登录，直接进入
		/*if(user.isAuthenticated()) {
			doResult(response, true, getCurrentFactoryUser(), "登录成功");
			return;
		}*/
		shiroLogin(response, userName, password, UserType.FACTORY, code);
	}
	
	@RequestMapping(value="/agencyLogin", method = {RequestMethod.POST, RequestMethod.GET})
	@ResponseBody
	public void agencyLogin(HttpServletRequest request, HttpServletResponse response, 
			String userName, String password, String type, String code) throws IOException {
		System.out.println("===用户登录功能========");
		
		if(StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)) {
			doResult(response, false, null, "用户名或密码不能为空");
            return;
		}

		shiroLogin(response, userName, password, UserType.AGENCY, code);
	}
	
	
	/**
	 * Description:系统平台登录接口
	 * @author around
	 * @date 2017年10月23日下午5:03:43
	 */
	@RequestMapping(value="/login", method = {RequestMethod.POST, RequestMethod.GET})
	@ResponseBody
	public void systemLogin(HttpServletRequest request, HttpServletResponse response, 
			String userName, String password, String type, String code) throws IOException {
		System.out.println("===用户登录功能========");
		
		if(StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)) {
			doResult(response, false, null, "用户名或密码不能为空");
            return ;
		}
		shiroLogin(response, userName, password, UserType.SYSTEM, code);
		//response.sendRedirect("/index");
	}
	
	
	/**
	 * Description:shiro登录
	 * @param response
	 * @param userName
	 * @param password
	 * @param type
	 * @param code
	 * @author around
	 * @date 2017年10月23日下午4:15:56
	 */
	private void shiroLogin(HttpServletResponse response, 
			String userName, String password, String type, String code) {
		//执行shiro认证
		Subject user = SecurityUtils.getSubject();
		System.out.println("user.isAuthenticated: " + user.isAuthenticated());
		System.out.println("user.isRemembered: " + user.isRemembered());
				
		CustomLoginToken token = new CustomLoginToken(userName, 
        		DigestUtils.md5Hex(password), type);
        token.setRememberMe(true);
        try {
            user.login(token);
        } catch (ServiceException e) {
        	logger.error("登录状态校验失败，请重试", e);
            doResult(response, false, StatusCode.NORETRUNDATA, null, "登录状态校验失败，请重试");
            return;
        } catch (UnknownAccountException e) {
        	logger.error("账号不存在", e);
            doResult(response, false, StatusCode.NORETRUNDATA, null, "用户名不存在");
            return;
        } catch (DisabledAccountException e) {
        	logger.error("账号未启用", e);
            doResult(response, false, StatusCode.NORETRUNDATA, null, "账号未启用");
            return;
        } catch (IncorrectCredentialsException e) {
        	logger.error("密码错误", e);
            doResult(response, false,StatusCode.NORETRUNDATA, null, "密码错误");
            return;
        } catch (RuntimeException e) {
        	logger.error("未知错误,请联系管理员", e);
            doResult(response, false,StatusCode.NORETRUNDATA, null, "未知错误,请联系管理员");
            return;
        }
		doResult(response, true, StatusCode.LOGING, UserUtils.getCurrentUser(), "登录成功!");
	}
	
	
	
	/**
	 * 用户退出
	 * @param session
	 */
	@RequestMapping(value="/loginout", method = {RequestMethod.POST, RequestMethod.GET})
	@ResponseBody
	public void loginOut(HttpSession session, HttpServletResponse response) {
		session.removeAttribute(CommonConstants.USERINFO);
		logger.info("===用户退出===");
		Subject subject = SecurityUtils.getSubject();
		System.out.println("user.isAuthenticated: " + subject.isAuthenticated());
		System.out.println("user.isRemembered: " + subject.isRemembered());
		subject.logout();
		
		//return "redirect:/tologin";
		doResult(response, true, StatusCode.TOLOGINOUT, null, "退出成功");
	}

	
	/**
	 * 会话失效
	 * @param session
	 * @param response
	 */
	@RequestMapping(value="/sessionFailure", method = {RequestMethod.POST, RequestMethod.GET})
	@ResponseBody
	public void sessionFailure(HttpSession session, HttpServletResponse response) {
		doResult(response, false, StatusCode.LOGINOUT, null, ResultType.LOGINOUT);
	}
	
	/**
	 * 没有权限
	 * @param session
	 * @param response
	 */
	@RequestMapping(value="/permissionsFailure", method = {RequestMethod.POST, RequestMethod.GET})
	@ResponseBody
	public void permissionsFailure(HttpSession session, HttpServletResponse response) {
		doResult(response, false, StatusCode.NOPERMISS, null, "权限不足");
	}
	

	/**
	 * 获取验证码 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/code")
	public String getYzm(HttpServletRequest request, HttpServletResponse response) throws Exception {

		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		// 定义图片长度和宽度
		int width = 60, height = 30;
		// 创建内存图像
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		Graphics g = image.getGraphics();
		Random random = new Random();
		g.setColor(getRandColor(200, 250));
		g.fillRect(0, 0, width, height);
		g.setFont(new Font("Times New Roman", Font.BOLD, 22));
		g.setColor(new Color(255, 255, 255));
		g.drawRect(0, 0, width - 1, height - 1);
		g.setColor(getRandColor(160, 200));
		for (int i = 0; i < 155; i++) {
			int x = random.nextInt(width), y = random.nextInt(height), xl = random.nextInt(12), yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}
		// 随机获取四位字母或数字型字符
		String str = "ABCDEFGHJKMNPQRSTUVWXYZ123456789";
		StringBuilder sb = new StringBuilder(4);
		for (int i = 0; i < 4; i++) {
			char ch = str.charAt(new Random().nextInt(str.length()));
			sb.append(ch);
		}
		String code = sb.toString().toLowerCase();
		System.out.println("验证码：" + code);
		logger.info("验证码：" + code);
		g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
		g.drawString(code, 6, 20);
		HttpSession session = request.getSession();
		session.setAttribute("code", code);
		g.dispose();
		ImageIO.write(image, "JPEG", response.getOutputStream());
		return null;
	}

	private Color getRandColor(int fc, int bc) {
		Random random = new Random();
		if (fc > 255)
			fc = 255;
		if (bc > 255)
			bc = 255;
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}
}
